// ReSharper disable CppTooWideScopeInitStatement
// ReSharper disable CppMemberFunctionMayBeStatic
// ReSharper disable CppTooWideScope

#include "HttpConnection.h"
#include <iostream>

#include "Config.h"

HttpConnection::HttpConnection(boost::asio::io_context& io_context)
    : _timeout_seconds(Config::GetInstance()._http_timeout), _socket(io_context),
      _deadline(io_context, std::chrono::seconds(_timeout_seconds)) {
}

void HttpConnection::Start() {
    auto self = shared_from_this();
    http::async_read(_socket, _buffer, _request,
                     [self, this](const beast::error_code& ec, std::size_t bytes_transferred) {
                         try {
                             if (ec) {
                                 std::cerr << "读取失败: " << ec.message() << std::endl;
                                 return;
                             }
                             //消耗掉缓冲区的字节
                             boost::ignore_unused(bytes_transferred);
                             self->HandleRequest();
                             self->CheckDeadLine();
                             self->_deadline.expires_after(std::chrono::seconds(_timeout_seconds));
                         }
                         catch (const std::exception& e) {
                             std::cerr << e.what() << std::endl;
                         }
                     });
}

void HttpConnection::HandleRequest() {
    _response.version(_request.version());
    _response.keep_alive(_request.keep_alive());
    _response.set(http::field::content_type, "text/json");
    try {
        //解析路径参数
        PreParseGetParam();
        const bool success = LogicSystem::GetInstance()->HandleHttp(_request.method(),
                                                                    _get_url, shared_from_this());
    }
    catch (std::exception& e) {
        std::cerr << "url 解析失败: " << e.what() << std::endl;
    }
    WriteResponse();
}

void HttpConnection::WriteResponse() {
    auto self = shared_from_this();
    _response.content_length(_response.body().size());
    http::async_write(_socket, _response, [self, this](boost::system::error_code ec, std::size_t) {
        if (ec) {
            std::cerr << "写入失败: " << ec.message() << std::endl;
        }
        if (!_request.keep_alive()) {
            //发送完成后断开连接
            self->_socket.shutdown(tcp::socket::shutdown_both, ec);
        }
        self->_deadline.cancel();
    });
}

void HttpConnection::CheckDeadLine() {
    auto self = shared_from_this();
    _deadline.async_wait(
        [self](beast::error_code ec) {
            if (!ec) {
                // Close socket to cancel any outstanding operation.
                self->_socket.close(ec);
            }
        });
}

void HttpConnection::PreParseGetParam() {
    // 提取 URI
    const auto uri = _request.target();
    // 查找查询字符串的开始位置（即 '?' 的位置）
    const auto query_pos = uri.find('?');
    if (query_pos == std::string::npos) {
        _get_url = uri;
        return;
    }
    _get_url = uri.substr(0, query_pos);
    std::string query_string = uri.substr(query_pos + 1);
    std::string key;
    std::string value;
    size_t pos = 0;
    while ((pos = query_string.find('&')) != std::string::npos) {
        auto pair = query_string.substr(0, pos);
        const size_t eq_pos = pair.find('=');
        if (eq_pos != std::string::npos) {
            key = UrlDecode(pair.substr(0, eq_pos));
            value = UrlDecode(pair.substr(eq_pos + 1));
            _get_params[key] = value;
        }
        query_string.erase(0, pos + 1);
    }
    // 处理最后一个参数对（如果没有 & 分隔符）
    if (!query_string.empty()) {
        const size_t eq_pos = query_string.find('=');
        if (eq_pos != std::string::npos) {
            key = UrlDecode(query_string.substr(0, eq_pos));
            value = UrlDecode(query_string.substr(eq_pos + 1));
            _get_params[key] = value;
        }
    }
}

unsigned char HttpConnection::ToHex(const unsigned char x) {
    return x > 9 ? x + 55 : x + 48;
}

unsigned char HttpConnection::FromHex(const unsigned char x) {
    unsigned char y = 0;
    if (x >= 'A' && x <= 'Z') y = x - 'A' + 10;
    else if (x >= 'a' && x <= 'z') y = x - 'a' + 10;
    else if (x >= '0' && x <= '9') y = x - '0';
    else
        throw std::exception("url decode error");
    return y;
}

std::string HttpConnection::UrlEncode(const std::string& str) {
    std::string strTemp;
    const size_t length = str.length();
    for (size_t i = 0; i < length; i++) {
        //判断是否仅有数字和字母构成
        if (isalnum(static_cast<unsigned char>(str[i])) ||
            (str[i] == '-') ||
            (str[i] == '_') ||
            (str[i] == '.') ||
            (str[i] == '~'))
            strTemp += str[i];
        else if (str[i] == ' ') //为空字符
            strTemp += "+";
        else {
            //其他字符需要提前加%并且高四位和低四位分别转为16进制
            strTemp += '%';
            strTemp += ToHex(static_cast<unsigned char>(str[i]) >> 4); // NOLINT(*-narrowing-conversions)
            strTemp += ToHex(static_cast<unsigned char>(str[i]) & 0x0F); // NOLINT(*-narrowing-conversions)
        }
    }
    return strTemp;
}

std::string HttpConnection::UrlDecode(const std::string& str) {
    std::string strTemp;
    const size_t length = str.length();
    for (size_t i = 0; i < length; i++) {
        //还原+为空
        if (str[i] == '+')
            strTemp += ' ';
            //遇到%将后面的两个字符从16进制转为char再拼接
        else if (str[i] == '%') {
            if (i + 2 < length) {
                // throw std::exception("url decode error");
            }
            const unsigned char high = FromHex(static_cast<unsigned char>(str[++i]));
            const unsigned char low = FromHex(static_cast<unsigned char>(str[++i]));
            strTemp += high * 16 + low; // NOLINT(*-narrowing-conversions, *-string-integer-assignment)
        }
        else strTemp += str[i];
    }
    return strTemp;
}

boost::asio::ip::tcp::socket& HttpConnection::GetSocket() {
    return _socket;
}